package svrConnectMgr

import (
	"encoding/base32"
	"fmt"
	"fronter/config"
	redisgw "fronter/redisGw"
	"log"
	"net"
	"net/http"
	"os"
	"sync"

	"github.com/gorilla/websocket"

	"github.com/sirupsen/logrus"
)

type ClientInterface interface {
	write([]byte)
	read()
	start_push()
}

var clientRwLock sync.RWMutex
var clientTcpMap map[string]ClientInterface
var HandleCallback func(proto_name string, data []byte) (string, []byte)

func init() {
	clientTcpMap = make(map[string]ClientInterface)
}

func addToWsClienManager(conn *websocket.Conn) {
	clientRwLock.Lock()
	defer clientRwLock.Unlock()
	user_identify := base32.StdEncoding.EncodeToString([]byte(conn.RemoteAddr().String()))
	clientTcpMap[user_identify] = wsClient{
		conn:           conn,
		chan_to_client: make(chan []byte),
	}
	logrus.Info("ws client:", user_identify, ", start handle conn.")
	go clientTcpMap[user_identify].start_push()
	clientTcpMap[user_identify].read()
}

type wsSvr struct {
}

var upgrader = websocket.Upgrader{
	ReadBufferSize:  4096,
	WriteBufferSize: 4096,
	// 解决跨域问题
	CheckOrigin: func(r *http.Request) bool {
		return true
	},
} // use default options
func (s *wsSvr) handleProto(w http.ResponseWriter, r *http.Request) {
	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Print("upgrade:", err)
		return
	}
	defer conn.Close()
	addToWsClienManager(conn)
}

func (s *wsSvr) listen(port int) (net.Listener, error) {
	http.HandleFunc("/proto", s.handleProto)
	socket, err := net.Listen("tcp", fmt.Sprintf("0.0.0.0:%d", port))
	if err != nil {
		logrus.Errorln("wssocket listen in ", port, "err! ", err.Error())
		return nil, err
		//err := http.ListenAndServe(fmt.Sprintf("0.0.0.0:%d", port), nil)
	}
	logrus.Infoln("start listen ws tcp in :", port)

	return socket, err
}

type Server struct {
	//udpServer udpSvr
	//tcpServer tcpSvr
	wsServer wsSvr
}

func (s Server) Listen(port int) {
	portRange := config.Get().PortRange
	for i := 0; i < int(portRange); i++ {
		socket, err := s.wsServer.listen(port + i)
		if err == nil {
			logrus.Infoln("svr success listen in :", port+i)
			redisgw.RegisterSvr(uint32(port + i))
			inner_ws_server := &http.Server{Addr: fmt.Sprintf("0.0.0.0:%d", port), Handler: nil}
			inner_ws_server.Serve(socket) //手动处理socket的accept
			return
		}
	}
	logrus.Errorln("failed to listen port!")
	os.Exit(-5)
}
